home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_se / base_class.e < prev    next >
Text File  |  2000-03-25  |  32KB  |  1,267 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
  4. --                       http://SmallEiffel.loria.fr
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
  11. -- for  more  details.  You  should  have  received a copy of the GNU General
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class BASE_CLASS
  17.    --
  18.    -- Internal representation of an Eiffel source base class.
  19.    --
  20.  
  21. inherit GLOBALS;
  22.  
  23. creation {EIFFEL_PARSER, TYPE_NONE} make
  24.  
  25. feature
  26.  
  27.    id: INTEGER;
  28.      -- To produce compact C code.
  29.  
  30.    path: STRING;
  31.      -- Access to the corresponding file.
  32.  
  33.    index_list: INDEX_LIST;
  34.      -- For the indexing of the class.
  35.  
  36.    heading_comment1: COMMENT;
  37.      -- Comment before keyword `class'.
  38.  
  39.    is_deferred: BOOLEAN;
  40.      -- True if class itself is deferred or if at least one
  41.      -- feature is deferred;
  42.  
  43.    is_expanded: BOOLEAN;
  44.      -- True if class itself is expanded.
  45.  
  46.    name: CLASS_NAME;
  47.      -- The name of the class.
  48.  
  49.    formal_generic_list: FORMAL_GENERIC_LIST;
  50.      -- Formal generic args if any.
  51.  
  52.    heading_comment2: COMMENT;
  53.      -- Comment after class name.
  54.  
  55.    obsolete_type_string: MANIFEST_STRING;
  56.      -- To warn user if any.
  57.  
  58.       parent_list: PARENT_LIST;
  59.       -- The contents of the inherit clause if any.
  60.  
  61.       creation_clause_list: CREATION_CLAUSE_LIST;
  62.       -- Constructor list.
  63.  
  64.       feature_clause_list: FEATURE_CLAUSE_LIST;
  65.       -- Features.
  66.  
  67.       class_invariant: CLASS_INVARIANT;
  68.       -- If any, the class invariant.
  69.  
  70.       end_comment: COMMENT;
  71.       -- Comment after end of class.
  72.  
  73. feature {NONE}
  74.  
  75.    feature_dictionary: DICTIONARY[E_FEATURE,STRING];
  76.      -- All features really defined in the current class.
  77.      -- Thus, it is the same features contained in
  78.      -- `feature_clause_list' (this dictionary speed up
  79.      -- feature look up).
  80.      -- To avoid clash between infix and prefix names,
  81.      -- access key IS NOT `to_string' but `to_key' of class
  82.      -- NAME.
  83.  
  84.    make(my_path, my_name: STRING; my_id: INTEGER) is
  85.       require
  86.      my_path = string_aliaser.item(my_path);
  87.      my_name = string_aliaser.item(my_name);
  88.      my_name /= as_none implies my_id > 0
  89.       do
  90.      path := my_path;
  91.      !!name.unknown_position(my_name);
  92.      id := my_id;
  93.      small_eiffel.add_base_class(Current);
  94.      !!isom.with_capacity(16);
  95.      !!feature_dictionary.make;
  96.       end;
  97.  
  98. feature {TYPE_CLASS}
  99.  
  100.    smallest_ancestor(type, other: TYPE): TYPE is
  101.      -- To help implementation of TYPE.smallest_ancestor while one
  102.      -- have to consider parents.
  103.      -- Note that `type' is directly related to `Current'.
  104.       require
  105.      type.is_run_type;
  106.      other.is_run_type;
  107.      type.base_class = Current;
  108.      not other.is_any;
  109.      not other.is_none;
  110.      other.base_class /= Void
  111.       do
  112.      if is_any then
  113.         Result := type;
  114.      elseif type.run_time_mark = other.run_time_mark then
  115.         Result := type;
  116.      elseif parent_list = Void then
  117.         Result := type_any;
  118.      elseif other.base_class.parent_list = Void then
  119.         Result := type_any;
  120.      else
  121.         Result := parent_list.smallest_ancestor(type,other);
  122.      end;
  123.       ensure
  124.      Result /= Void
  125.       end;
  126.  
  127. feature {SHORT,PARENT_LIST}
  128.  
  129.    up_to_any_in(pl: FIXED_ARRAY[BASE_CLASS]) is
  130.       do
  131.      if is_general then
  132.      else
  133.         if not pl.fast_has(Current) then
  134.            pl.add_last(Current);
  135.         end;
  136.         if parent_list = Void then
  137.            if not pl.fast_has(class_any) then
  138.           pl.add_last(class_any);
  139.            end;
  140.         else
  141.            parent_list.up_to_any_in(pl);
  142.         end;
  143.      end;
  144.       end;
  145.  
  146. feature
  147.  
  148.    expanded_initializer(t: TYPE): RUN_FEATURE_3 is
  149.       require
  150.      t.is_expanded
  151.       do
  152.      if creation_clause_list /= Void then
  153.         Result := creation_clause_list.expanded_initializer(t);
  154.      end;
  155.       end;
  156.  
  157. feature {RUN_CLASS}
  158.  
  159.    get_default_rescue(rc: RUN_CLASS; n: FEATURE_NAME): RUN_FEATURE_3 is
  160.       local
  161.      general: BASE_CLASS;
  162.      p: PROCEDURE;
  163.      fn1, fn2: FEATURE_NAME;
  164.       do
  165.      general := class_general;
  166.      if Current /= general then
  167.         p := general.general_default_rescue;
  168.         if p /= Void then
  169.            fn1 := p.first_name;
  170.            fn2 := new_name_of(general,fn1);
  171.            if fn2.to_string /= n.to_string then
  172.           p ?= look_up_for(rc,fn2);
  173.           if p /= Void then
  174.              Result := p.a_default_rescue(rc,fn2);
  175.           end;
  176.            end;
  177.         end;
  178.      end;
  179.       end;
  180.  
  181.    check_expanded_with(t: TYPE) is
  182.       require
  183.      t.is_expanded;
  184.      t.base_class = Current
  185.       local
  186.      rf: RUN_FEATURE;
  187.       do
  188.      if is_deferred then
  189.         eh.add_type(t,fz_is_invalid);
  190.         fatal_error(" A deferred class must not be expanded (VTEC.1).");
  191.      end;
  192.      if creation_clause_list /= Void then
  193.         creation_clause_list.check_expanded_with(t);
  194.      end;
  195.      rf := expanded_initializer(t);
  196.       end;
  197.  
  198. feature {RUN_FEATURE,ONCE_ROUTINE_POOL}
  199.  
  200.    once_flag(mark: STRING): BOOLEAN is
  201.      -- Flag used to avoid double C definition of globals
  202.      -- C variables for once routines.
  203.       require
  204.      mark = string_aliaser.item(mark);
  205.      small_eiffel.is_ready
  206.       do
  207.      if once_mark_list = Void then
  208.         !!once_mark_list.with_capacity(4);
  209.         once_mark_list.add_last(mark);
  210.      elseif once_mark_list.fast_has(mark) then
  211.         Result := true;
  212.      else
  213.         once_mark_list.add_last(mark);
  214.      end;
  215.       ensure
  216.      once_flag(mark)
  217.       end;
  218.  
  219. feature {NONE}
  220.  
  221.    once_mark_list: FIXED_ARRAY[STRING];
  222.      -- When the tag is in the list, the corresponding routine
  223.      -- does not use Current and C code is already written.
  224.  
  225. feature {TYPE_FORMAL_GENERIC}
  226.  
  227.    first_parent_for(other: like Current): PARENT is
  228.      -- Assume `other' is a parent of Current, gives
  229.      -- the closest PARENT of Current going to `other'.
  230.       require
  231.      is_subclass_of(other);
  232.      parent_list /= Void
  233.       do
  234.      Result := parent_list.first_parent_for(other);
  235.       ensure
  236.      Result /= Void
  237.       end;
  238.  
  239.    next_parent_for(other: like Current; previous: PARENT): like previous is
  240.      -- Gives the next one or Void.
  241.       require
  242.      is_subclass_of(other);
  243.      parent_list /= Void
  244.       do
  245.      Result := parent_list.next_parent_for(other,previous);
  246.       end;
  247.  
  248. feature
  249.  
  250.    new_name_of(top: BASE_CLASS; top_fn: FEATURE_NAME): FEATURE_NAME is
  251.      -- Assume, `top_fn' is a valid notation to denote a feature of `top'.
  252.      -- It computes the corresponding name (taking in account possible 
  253.      -- rename/select) to use this feature down in class hierarchy (in 
  254.      -- the Current base_class).
  255.       require
  256.      Current = top or else Current.is_subclass_of(top);
  257.      top_fn /= Void
  258.       do
  259.      if Current = top then
  260.         Result := top_fn;
  261.      else
  262.         Result := top.up_to_original(Current,top_fn);
  263.         if Result = Void then
  264.            eh.add_position(top_fn.start_position);
  265.            eh.append(fz_09);
  266.            eh.append(top_fn.to_string);
  267.            eh.append("%" from %"");
  268.            eh.append(top.name.to_string);
  269.            eh.append("%" not found in %"");
  270.            eh.append(name.to_string);
  271.            fatal_error("%".");
  272.         end;
  273.      end;
  274.       ensure
  275.      Result /= Void
  276.       end;
  277.  
  278. feature {BASE_CLASS,PARENT}
  279.  
  280.    up_to_original(bottom: BASE_CLASS; top_fn: FEATURE_NAME): FEATURE_NAME is
  281.      -- Assume `top_fn' is a valid name in `bottom'. Try to go up in the 
  282.      -- hierarchy to retrieve the original name of the feature.
  283.       require
  284.      top_fn /= Void;
  285.      Current = bottom or else bottom.is_subclass_of(Current)
  286.       do
  287.      if proper_has(top_fn) then
  288.         if parent_list = Void then
  289.            Result := bottom.new_name_of_original(Current,top_fn);
  290.         else
  291.            Result := parent_list.up_to_original(bottom,top_fn);
  292.            if Result = Void then
  293.           Result := bottom.new_name_of_original(Current,top_fn);
  294.            end;
  295.         end;
  296.      elseif parent_list /= Void then
  297.         Result := parent_list.up_to_original(bottom,top_fn);
  298.      elseif is_general then
  299.      else
  300.         Result := class_any.up_to_original(bottom,top_fn);
  301.      end;
  302.       end;
  303.  
  304. feature {RUN_FEATURE_1,PARENT,BASE_CLASS}
  305.  
  306.    original_name(top: BASE_CLASS; bottom_fn: FEATURE_NAME): FEATURE_NAME is
  307.      -- Assume that `bottom_fn' is a valid name in `Current'. Compute the 
  308.      -- original definition name going up in the hierarchy to `top'.
  309.       require
  310.      bottom_fn /= Void;
  311.      Current = top or else Current.is_subclass_of(top)
  312.       do
  313.      if Current = top then
  314.         check proper_has(bottom_fn) end;
  315.         Result := bottom_fn;
  316.      elseif parent_list /= Void then
  317.         Result := parent_list.original_name(top,bottom_fn);
  318.      else
  319.         Result := top.original_name(top,bottom_fn);
  320.         if Result = Void then
  321.            Result := bottom_fn;
  322.            eh.add_position(bottom_fn.start_position);
  323.            eh.append(top.name.to_string);
  324.            eh.append("<---");
  325.            eh.append(name.to_string);
  326.            eh.append(". BASE_CLASS.original_name, Not Yet Implemented.");
  327.            eh.print_as_warning;
  328.         end;
  329.      end;
  330.       ensure
  331.      Result /= Void
  332.       end;
  333.  
  334. feature {BASE_CLASS}
  335.  
  336.    new_name_of_original(top: BASE_CLASS; top_fn: FEATURE_NAME): FEATURE_NAME is
  337.      -- Compute rename/select to go down in class hierarchy. In the very 
  338.      -- first call, `top_fn' is the name used in `top'.
  339.       require
  340.      top_fn /= Void;
  341.      top.proper_has(top_fn);
  342.      Current = top or else Current.is_subclass_of(top)
  343.       do
  344.      if Current = top then
  345.         Result := top_fn;
  346.      elseif is_general then
  347.         Result := top_fn;
  348.      else
  349.         if parent_list = Void then
  350.            Result := class_any.new_name_of(top,top_fn);
  351.         else
  352.            going_up_trace.clear;
  353.            Result := parent_list.going_up(going_up_trace,top,top_fn);
  354.         end;
  355.      end;
  356.       ensure
  357.      Result /= Void
  358.       end;
  359.  
  360.    general_default_rescue: PROCEDURE is
  361.       do
  362.      if feature_dictionary.has(as_default_rescue) then
  363.         Result ?= feature_dictionary.at(as_default_rescue);
  364.      end;
  365.       end;
  366.  
  367. feature {BASE_CLASS,PARENT_LIST,PARENT}
  368.  
  369.    going_up(trace: FIXED_ARRAY[PARENT]; top: BASE_CLASS;
  370.         top_fn: FEATURE_NAME;): FEATURE_NAME is
  371.       require
  372.      Current /= top;
  373.       do
  374.      if parent_list = Void then
  375.         Result := class_any.going_up(trace,top,top_fn);
  376.      else
  377.         Result := parent_list.going_up(trace,top,top_fn);
  378.      end;
  379.       end;
  380.  
  381. feature {NONE}
  382.  
  383.    going_up_trace: FIXED_ARRAY[PARENT] is
  384.       once
  385.      !!Result.with_capacity(8);
  386.       end;
  387.  
  388. feature
  389.  
  390.    mapping_c_in(str: STRING) is
  391.       do
  392.      str.extend('B');
  393.      str.extend('C');
  394.      id.append_in(str);
  395.       end;
  396.  
  397.    mapping_c is
  398.       local
  399.      s: STRING;
  400.       do
  401.      s := "        ";
  402.      s.clear;
  403.      mapping_c_in(s);
  404.      cpp.put_string(s);
  405.       end;
  406.  
  407. feature {EIFFEL_PARSER}
  408.  
  409.    add_index_clause(index_clause: INDEX_CLAUSE) is
  410.       require
  411.      index_clause /= Void
  412.       do
  413.      if index_list = Void then
  414.         !!index_list.make(index_clause);
  415.      else
  416.         index_list.add_last(index_clause);
  417.      end;
  418.       end;
  419.  
  420.    add_creation_clause(cc: CREATION_CLAUSE) is
  421.       require
  422.      cc /= Void
  423.       do
  424.      if creation_clause_list = Void then
  425.         !!creation_clause_list.make(cc);
  426.      else
  427.         creation_clause_list.add_last(cc);
  428.      end;
  429.       end;
  430.  
  431.    add_feature_clause(fc: FEATURE_CLAUSE) is
  432.       require
  433.      fc /= Void
  434.       do
  435.      if feature_clause_list = Void then
  436.         !!feature_clause_list.make(fc);
  437.      else
  438.         feature_clause_list.add_last(fc);
  439.      end;
  440.       end;
  441.  
  442.    set_is_deferred is
  443.       do
  444.      if is_expanded then
  445.         error_vtec1;
  446.      end;
  447.      is_deferred := true;
  448.       end;
  449.  
  450.    set_is_expanded is
  451.       do
  452.      if is_deferred then
  453.         error_vtec1;
  454.      end;
  455.      is_expanded := true;
  456.       end;
  457.  
  458.    set_formal_generic_list(fgl: like formal_generic_list) is
  459.       do
  460.      formal_generic_list := fgl;
  461.       end;
  462.  
  463.    set_heading_comment1(hc: like heading_comment1) is
  464.       do
  465.      heading_comment1 := hc;
  466.       end;
  467.  
  468.    set_heading_comment2(hc: like heading_comment2) is
  469.       do
  470.      heading_comment2 := hc;
  471.       end;
  472.  
  473.    set_parent_list(sp: POSITION; c: COMMENT; l: ARRAY[PARENT]) is
  474.       require
  475.      not sp.is_unknown;
  476.      c /= Void or else l /= Void;
  477.      l /= Void implies not l.is_empty;
  478.       do
  479.      !!parent_list.make(Current,sp,c,l);
  480.       end;
  481.  
  482.    set_end_comment(ec: like end_comment) is
  483.       do
  484.      end_comment := ec;
  485.       end;
  486.  
  487.    set_obsolete_type_string(ots: like obsolete_type_string) is
  488.       do
  489.      obsolete_type_string := ots;
  490.      if obsolete_type_string /= Void then
  491.         if small_eiffel.short_flag then
  492.         elseif small_eiffel.pretty_flag then
  493.         else
  494.            eh.append("Class ");
  495.            eh.append(name.to_string);
  496.            eh.append(" is obsolete :%N");
  497.            eh.append(obsolete_type_string.to_string);
  498.            eh.add_position(name.start_position);
  499.            eh.print_as_warning;
  500.            end
  501.         end;
  502.      end;
  503.  
  504.      set_invariant(sp: POSITION; hc: COMMENT; al: ARRAY[ASSERTION]) is
  505.       do
  506.      if hc /= Void or else al /= Void then
  507.         !!class_invariant.make(sp,hc,al);
  508.      end;
  509.       end;
  510.  
  511.    get_started is
  512.       do
  513.      if feature_clause_list /= Void then
  514.         feature_clause_list.get_started(feature_dictionary);
  515.      end;
  516.      if parent_list /= Void then
  517.         parent_list.get_started;
  518.      end;
  519.      if end_comment /= Void then
  520.         end_comment.good_end(name);
  521.      end;
  522.      if parent_list /= Void then
  523.         visited.clear;
  524.         visited.add_last(Current);
  525.         parent_list.inherit_cycle_check;
  526.      end;
  527.      if run_control.all_check and then
  528.         is_deferred and then
  529.         creation_clause_list /= Void
  530.       then
  531.         eh.add_position(name.start_position);
  532.         warning(creation_clause_list.start_position,
  533.             "Deferred class should not have %
  534.             %creation clause (VGCP.1).");
  535.      end;
  536.       end;
  537.  
  538. feature
  539.  
  540.    get_copy: E_FEATURE is
  541.       do
  542.      Result := feature_dictionary.at(as_copy);
  543.       ensure
  544.      Result /= Void
  545.       end;
  546.  
  547.    clients_for(fn: FEATURE_NAME): CLIENT_LIST is
  548.      -- Looking up for the clients list when calling feature `fn' with 
  549.      -- some object from current class. Assume `fn' exists.
  550.       do
  551.      if proper_has(fn) then
  552.         Result := feature_dictionary.at(fn.to_key).clients;
  553.      elseif is_general then
  554.      elseif parent_list = Void then
  555.         Result := class_any.clients_for(fn);
  556.      else
  557.         check
  558.            parent_list.count >= 1
  559.         end;
  560.         Result := parent_list.clients_for(fn);
  561.      end;
  562.       ensure
  563.      -- *** ??? Result /= Void
  564.       end;
  565.  
  566.    has_creation_clause: BOOLEAN is
  567.       do
  568.      Result := creation_clause_list /= Void;
  569.       end;
  570.  
  571.    has_creation(proc_name: FEATURE_NAME): BOOLEAN is
  572.      -- Is `proc_name' the name of a creation procedure ?
  573.      -- Also check that `proc_name' is written in an allowed
  574.      -- base class for creation.
  575.       require
  576.      proc_name.origin_base_class /= Void
  577.       local
  578.      cc: CREATION_CLAUSE;
  579.      bc: BASE_CLASS;
  580.      cn: CLASS_NAME;
  581.       do
  582.      if creation_clause_list = Void then
  583.         eh.append(name.to_string);
  584.         eh.append(" has no creation clause.");
  585.         eh.add_position(proc_name.start_position);
  586.         eh.print_as_error;
  587.      else
  588.         cc := creation_clause_list.get_clause(proc_name);
  589.         if cc = Void then
  590.            eh.append(fz_09);
  591.            eh.append(proc_name.to_string);
  592.            eh.append("%" does not belong to a creation clause of ");
  593.            eh.append(name.to_string);
  594.            error(proc_name.start_position,fz_dot);
  595.         else
  596.            Result := true;
  597.            bc := proc_name.origin_base_class;
  598.            if bc /= Void then
  599.           cn := bc.name;
  600.           Result := cc.clients.gives_permission_to(cn);
  601.            end;
  602.         end;
  603.      end;
  604.      if not Result then
  605.         error(proc_name.start_position,"Creation Call not allowed.");
  606.      end;
  607.       end;
  608.  
  609. feature {SMALL_EIFFEL,BASE_CLASS}
  610.  
  611.    root_procedure_name(procedure_name: STRING): SIMPLE_FEATURE_NAME is
  612.      -- Look for the root procedure to start execution here.
  613.      -- Check that `procedure_name' is really a creation procedure.
  614.       require
  615.      not procedure_name.is_empty
  616.       do
  617.      if creation_clause_list = Void then
  618.         eh.add_position(name.start_position);
  619.         fatal_error("Bad root class (this class has no creation clause).");
  620.      else
  621.         Result := creation_clause_list.root_procedure_name(procedure_name);
  622.         if Result = Void then
  623.            eh.add_position(name.start_position);
  624.            eh.append("Bad root procedure name (%"");
  625.            eh.append(procedure_name);
  626.            fatal_error("%" is not a creation procedure of this class).");
  627.         end;
  628.      end;
  629.       ensure
  630.      Result /= Void
  631.       end;
  632.  
  633. feature {SMALL_EIFFEL}
  634.  
  635.    root_procedure(procedure_name: SIMPLE_FEATURE_NAME): PROCEDURE is
  636.      -- Look for the root procedure to start execution here.
  637.      -- Do some checking on the root class (not deferred, not generic,
  638.      -- really has `procedure_name' as a creation procedure etc.).
  639.      -- Return Void and print errors if needed.
  640.       require
  641.      procedure_name = root_procedure_name(procedure_name.to_string)
  642.       local
  643.      rc: RUN_CLASS;
  644.      f: E_FEATURE;
  645.       do
  646.      if is_generic then
  647.         eh.append(name.to_string);
  648.         eh.append(" cannot be a root class since it is a generic class.");
  649.         eh.print_as_fatal_error;
  650.      end;
  651.      if is_deferred then
  652.         eh.append(name.to_string);
  653.         eh.append(" cannot be a root class since it is a deferred class.");
  654.         eh.print_as_warning;
  655.      end;
  656.      rc := run_class;
  657.      rc.set_at_run_time;
  658.      f := look_up_for(rc,procedure_name);
  659.      if f = Void then
  660.         eh.add_position(procedure_name.start_position);
  661.         fatal_error("Root procedure not found.");
  662.      end;
  663.      Result ?= f;
  664.      if Result = Void then
  665.         eh.add_position(f.start_position);
  666.         fatal_error("Invalid Root (not a procedure).");
  667.      end;
  668.       ensure
  669.      Result /= Void
  670.       end;
  671.  
  672.    check_generic_formal_arguments is
  673.       do
  674.      if formal_generic_list /= Void then
  675.         formal_generic_list.check_generic_formal_arguments;
  676.      end;
  677.       end;
  678.  
  679.    id_extra_information(sfw: STD_FILE_WRITE) is
  680.       do
  681.      sfw.put_string("class-name: ");
  682.      sfw.put_string(name.to_string);
  683.      sfw.put_string(" parent-count: ");
  684.      if parent_list /= Void then
  685.         parent_list.id_extra_information(sfw);
  686.      else
  687.         sfw.put_string("0 ");
  688.      end;
  689.       end;
  690.  
  691. feature
  692.  
  693.    run_class: RUN_CLASS is
  694.       require
  695.      not is_generic
  696.       local
  697.      rcd: DICTIONARY[RUN_CLASS,STRING];
  698.      n: STRING;
  699.      type: TYPE_CLASS;
  700.       do
  701.      n := name.to_string;
  702.      rcd := small_eiffel.run_class_dictionary;
  703.      if rcd.has(n) then
  704.         Result := rcd.at(n);
  705.      else
  706.         !!type.make(name);
  707.         Result := type.run_class;
  708.      end;
  709.       end;
  710.  
  711.    current_type: TYPE is
  712.       do
  713.      Result := run_class.current_type;
  714.       end;
  715.  
  716.    is_generic: BOOLEAN is
  717.      -- When class is defined with generic arguments.
  718.       do
  719.      Result := formal_generic_list /= Void;
  720.       end;
  721.  
  722.    proper_has(fn: FEATURE_NAME): BOOLEAN is
  723.      -- True when `fn' is really written in current class.
  724.       do
  725.      Result := feature_dictionary.has(fn.to_key);
  726.       end;
  727.  
  728.    is_subclass_of(other: BASE_CLASS): BOOLEAN is
  729.      -- Is Current a subclass of `other' ?
  730.       require
  731.      other /= Current
  732.       do
  733.      if isom = Void then
  734.         -- Yes, it is the NONE class.
  735.         Result := true;
  736.      elseif isom.fast_has(other) then
  737.         Result := true;
  738.      elseif other.isom = Void then
  739.      else
  740.         if other.is_any then
  741.            Result := true;
  742.         else
  743.            visited.clear;
  744.            Result := is_subclass_of_aux(other);
  745.         end;
  746.         if Result then
  747.            isom.add_last(other);
  748.         end;
  749.      end;
  750.       end;
  751.  
  752. feature {NONE}
  753.  
  754.    visited: FIXED_ARRAY[BASE_CLASS] is
  755.      -- List of all visited classes to detects loops during
  756.      -- `is_subclass_of' processing.
  757.       once
  758.      !!Result.with_capacity(32);
  759.       end;
  760.  
  761. feature {PARENT_LIST,BASE_CLASS}
  762.  
  763.    inherit_cycle_check is
  764.       local
  765.      i: INTEGER;
  766.       do
  767.      visited.add_last(Current);
  768.      if visited.first = Current then
  769.         eh.append("Cyclic inheritance graph : ");
  770.         from
  771.            i := 0;
  772.         until
  773.            i > visited.upper
  774.         loop
  775.            eh.append(visited.item(i).name.to_string);
  776.            if i < visited.upper then
  777.           eh.append(", ");
  778.            end;
  779.            i := i + 1;
  780.         end;
  781.         fatal_error(", ...");
  782.      elseif parent_list /= Void then
  783.         parent_list.inherit_cycle_check;
  784.      end;
  785.       end;
  786.  
  787.    is_subclass_of_aux(c: BASE_CLASS): BOOLEAN is
  788.       require
  789.      not c.is_any;
  790.      Current /= c
  791.       do
  792.      if visited.fast_has(Current) then
  793.      else
  794.         visited.add_last(Current);
  795.         if parent_list /= Void then
  796.            Result := parent_list.has_parent(c);
  797.         elseif not visited.fast_has(class_any) then
  798.            Result := class_any.is_subclass_of_aux(c);
  799.         end;
  800.      end;
  801.       end;
  802.  
  803. feature
  804.  
  805.    is_any: BOOLEAN is
  806.       do
  807.      Result := as_any = name.to_string;
  808.       end;
  809.  
  810.    is_general: BOOLEAN is
  811.       do
  812.      Result := as_general = name.to_string;
  813.       end;
  814.  
  815.    has_redefine(fn: FEATURE_NAME): BOOLEAN is
  816.       require
  817.      fn /= Void
  818.       do
  819.      if parent_list /= Void then
  820.         Result := parent_list.has_redefine(fn)
  821.      end;
  822.       end;
  823.  
  824.    e_feature(fn: FEATURE_NAME): E_FEATURE is
  825.      -- Simple (and fast) look_up to see if `fn' exists here.
  826.       local
  827.      key: STRING;
  828.       do
  829.      key := fn.to_key;
  830.      if feature_dictionary.has(key) then
  831.         Result := feature_dictionary.at(key);
  832.      else
  833.         Result := super_e_feature(fn);
  834.      end;
  835.       end;
  836.  
  837.    has(fn: FEATURE_NAME): BOOLEAN is
  838.      -- Simple (and fast) look_up to see if `fn' exists here.
  839.       require
  840.      fn /= Void
  841.       do
  842.      Result := e_feature(fn) /= Void;
  843.       end;
  844.  
  845. feature {CALL_PROC_CALL}
  846.  
  847.    run_feature_for(rc: RUN_CLASS; target: EXPRESSION; 
  848.            fn: FEATURE_NAME; ct: TYPE): RUN_FEATURE is
  849.      -- Fetch the corresponding one in context `ct' (the type of Current).
  850.      -- Exporting rules are automatically checked and possible
  851.      -- rename are also done.
  852.      -- No return when an error occurs because `fatal_error' is called.
  853.       require
  854.      target.result_type.base_class = Current
  855.       local
  856.      top_bc: BASE_CLASS;
  857.      nfn: FEATURE_NAME;
  858.      constraint: TYPE;
  859.      type_formal_generic: TYPE_FORMAL_GENERIC;
  860.      bcn: CLASS_NAME;
  861.       do
  862.      check  
  863.         fn.to_string /= as_eq;
  864.         fn.to_string /= as_neq;
  865.      end;
  866.      -- Check constrained genericity first :
  867.      type_formal_generic ?= target.result_type;
  868.      if type_formal_generic /= Void then
  869.         constraint := type_formal_generic.constraint;
  870.         if constraint = Void then
  871.         elseif not type_formal_generic.is_a(constraint) then
  872.            eh.print_as_error;
  873.            eh.add_position(fn.start_position);
  874.            fatal_error("Constraint genericity violation.");
  875.         end;
  876.      end;
  877.      -- Then, compute possible rename :
  878.      nfn := fn;
  879.      top_bc := target.static_result_base_class;
  880.      if top_bc /= Void then
  881.         if Current = top_bc or else is_subclass_of(top_bc) then
  882.            if top_bc.has(fn) then
  883.           nfn := new_name_of(top_bc,fn);
  884.            end;
  885.         end;
  886.      end;
  887.      -- Search for the feature :
  888.      Result := rc.get_feature(nfn);
  889.      if Result = Void then
  890.         eh.feature_not_found(fn);
  891.         eh.print_as_fatal_error;
  892.      end;
  893.      -- Check export rules :
  894.      if not target.is_current then
  895.         bcn := ct.base_class.name;
  896.         if not Result.is_exported_in(bcn) then
  897.            eh.add_position(Result.start_position);
  898.            eh.append(" Cannot use feature %"");
  899.            eh.append(fn.to_string);
  900.            error(fn.start_position,"%" here.");
  901.            eh.add_position(fn.start_position);
  902.            eh.append("Forbidden call when type of Current is ");
  903.            eh.append(ct.run_time_mark);
  904.            fatal_error(fz_dot);
  905.         end;
  906.      end;
  907.      -- Finally, check for obsolete usage :
  908.      Result.base_feature.check_obsolete(fn.start_position);
  909.       ensure
  910.      Result /= Void
  911.       end;
  912.  
  913. feature {LOCAL_ARGUMENT,RUN_CLASS}
  914.  
  915.    has_simple_feature_name(sfn: STRING): BOOLEAN is
  916.      -- Simple (and fast) look_up to see if one feature of name
  917.      -- `n' exists here.
  918.       require
  919.      sfn = string_aliaser.item(sfn)
  920.       local
  921.      unknown_position: POSITION;
  922.       do
  923.      mem_fn.make(sfn,unknown_position);
  924.      Result := has(mem_fn);
  925.       end;
  926.  
  927. feature
  928.  
  929.    look_up_for(rc: RUN_CLASS; fn: FEATURE_NAME): E_FEATURE is
  930.      -- Gives Void or the good one to compute the runnable
  931.      -- version of `fn' in `rc'.
  932.      -- All inheritance rules are checked.
  933.       local
  934.      super: E_FEATURE;
  935.      fn_key: STRING;
  936.      cst_att: CST_ATT;
  937.      fnl: FEATURE_NAME_LIST;
  938.      super_fn: like fn;
  939.      i: INTEGER;
  940.       do
  941.      fn_key := fn.to_key;
  942.      if feature_dictionary.has(fn_key) then
  943.         Result := feature_dictionary.at(fn_key);
  944.         super :=  super_look_up_for(rc,fn);
  945.         if super /= Void then
  946.            vdrd6(rc,super,Result);
  947.            cst_att ?= super;
  948.            if cst_att /= Void then
  949.           eh.add_position(super.start_position);
  950.           eh.add_position(Result.start_position);
  951.           fatal_error("Constant feature cannot be redefined.");
  952.            end;
  953.            from
  954.           fnl := super.names;
  955.           i := fnl.count;
  956.            until
  957.           i < 1
  958.            loop
  959.           super_fn := fnl.item(i)
  960.           if super_fn.is_frozen then
  961.              if super_fn.to_key = fn_key then
  962.             eh.add_position(super_fn.start_position);
  963.             eh.add_position(Result.start_position);
  964.             fatal_error("Cannot redefine a frozen feature.");
  965.              end;
  966.           end;
  967.           i := i - 1;
  968.            end;
  969.            if not Result.can_hide(super,rc) then
  970.           eh.add_position(super.start_position);
  971.           eh.add_position(Result.start_position);
  972.           eh.append("Incompatible headings for redefinition.");
  973.           eh.print_as_warning;
  974.            end;
  975.            if super.is_deferred then
  976.            elseif has_redefine(fn) then
  977.            else
  978.           eh.add_position(Result.start_position);
  979.           eh.add_position(super.start_position);
  980.           eh.append("Invalid redefinition in ");
  981.           eh.append(name.to_string);
  982.           eh.append(". Missing redefine ?");
  983.           eh.print_as_error;
  984.            end;
  985.         end;
  986.      else
  987.         Result := super_look_up_for(rc,fn);
  988.      end;
  989.       end;
  990.  
  991. feature {NONE}
  992.  
  993.    super_look_up_for(rc: RUN_CLASS; fn: FEATURE_NAME): E_FEATURE is
  994.      -- Same work as `look_up_for' but do not look in current
  995.      -- base class.
  996.       require
  997.      rc /= Void;
  998.      fn /= Void;
  999.       do
  1000.      if parent_list = Void then
  1001.         if is_general then
  1002.            Result := Void;
  1003.         else
  1004.            Result := class_any.look_up_for(rc,fn);
  1005.         end;
  1006.      else
  1007.         Result := parent_list.look_up_for(rc,fn);
  1008.      end;
  1009.       end;
  1010.  
  1011. feature {RUN_CLASS,PARENT_LIST}
  1012.  
  1013.    collect_invariant(rc: RUN_CLASS) is
  1014.       require
  1015.      rc /= Void
  1016.       do
  1017.      if parent_list /= Void then
  1018.         parent_list.collect_invariant(rc);
  1019.      end;
  1020.      if class_invariant /= Void then
  1021.         assertion_collector.invariant_add_last(class_invariant);
  1022.      end;
  1023.       end;
  1024.  
  1025. feature {CLASS_INVARIANT,PARENT_LIST}
  1026.  
  1027.    header_comment_for(ci: CLASS_INVARIANT) is
  1028.       local
  1029.      ia: like class_invariant;
  1030.       do
  1031.      ia := class_invariant;
  1032.      if ia /= Void and then ia.header_comment /= Void then
  1033.         ci.set_header_comment(ia.header_comment);
  1034.      elseif parent_list /= Void then
  1035.         parent_list.header_comment_for(ci);
  1036.      end;
  1037.       end;
  1038.  
  1039. feature {RUN_FEATURE}
  1040.  
  1041.    run_require(rf: RUN_FEATURE): RUN_REQUIRE is
  1042.      -- Collect all (inherited) require assertions for `rf'.
  1043.       require
  1044.      rf.current_type.base_class = Current
  1045.       local
  1046.      ct: TYPE;
  1047.       do
  1048.      assertion_collector.require_start;
  1049.      ct := rf.current_type;
  1050.      collect_assertion(rf.name);
  1051.      Result := assertion_collector.require_end(rf,ct);
  1052.       end;
  1053.  
  1054.    run_ensure(rf: RUN_FEATURE): E_ENSURE is
  1055.      -- Collect all (inherited) ensure assertions for `rf'.
  1056.       require
  1057.      rf.current_type.base_class = Current
  1058.       local
  1059.      ct: TYPE;
  1060.       do
  1061.      assertion_collector.ensure_start;
  1062.      ct := rf.current_type;
  1063.      collect_assertion(rf.name);
  1064.      Result := assertion_collector.ensure_end(rf,ct);
  1065.       end;
  1066.  
  1067. feature {BASE_CLASS,PARENT_LIST}
  1068.  
  1069.    collect_assertion(fn: FEATURE_NAME) is
  1070.       require
  1071.      fn /= Void
  1072.       local
  1073.      fn_key: STRING;
  1074.       do
  1075.      fn_key := fn.to_key;
  1076.      if feature_dictionary.has(fn_key) then
  1077.         assertion_collector.assertion_add_last(feature_dictionary.at(fn_key));
  1078.      end;
  1079.      if parent_list = Void then
  1080.         if is_general then
  1081.         else
  1082.            class_any.collect_assertion(fn);
  1083.         end;
  1084.      else
  1085.         parent_list.collect_assertion(fn);
  1086.      end;
  1087.       end;
  1088.  
  1089. feature {NONE}
  1090.  
  1091.    mem_fn: SIMPLE_FEATURE_NAME is
  1092.      -- Dummy once name to avoid memory leaks.
  1093.       local
  1094.      unknown_position: POSITION;
  1095.       once
  1096.      !!Result.make(as_malloc,unknown_position);
  1097.       end;
  1098.  
  1099. feature {BASE_CLASS}
  1100.  
  1101.    isom: FIXED_ARRAY[BASE_CLASS];
  1102.      -- Memorize results to speed ud `is_subclass_of'.
  1103.  
  1104.    super_e_feature(fn: FEATURE_NAME): E_FEATURE is
  1105.  
  1106.       do
  1107.      if parent_list = Void then
  1108.         if is_general then
  1109.         else
  1110.            Result := class_any.e_feature(fn);
  1111.         end;
  1112.      else
  1113.         Result := parent_list.e_feature(fn);
  1114.      end;
  1115.       end;
  1116.  
  1117. feature
  1118.  
  1119.    pretty_print is
  1120.       do
  1121.      fmt.set_indent_level(0);
  1122.      if index_list /= Void then
  1123.         index_list.pretty_print;
  1124.         fmt.indent;
  1125.      end;
  1126.      if heading_comment1 /= Void then
  1127.         heading_comment1.pretty_print;
  1128.         fmt.indent;
  1129.      end;
  1130.      if is_deferred then
  1131.         fmt.keyword("deferred");
  1132.      elseif is_expanded then
  1133.         fmt.keyword(fz_expanded);
  1134.         end;
  1135.         fmt.keyword("class");
  1136.         name.pretty_print;
  1137.         if is_generic then
  1138.            formal_generic_list.pretty_print;
  1139.         end;
  1140.         fmt.indent;
  1141.         if obsolete_type_string /= Void then
  1142.            fmt.keyword("obsolete");
  1143.            obsolete_type_string.pretty_print;
  1144.         end;
  1145.         fmt.indent;
  1146.         if heading_comment2 /= Void then
  1147.            heading_comment2.pretty_print;
  1148.         end;
  1149.         if parent_list /= Void then
  1150.            parent_list.pretty_print;
  1151.         end;
  1152.         if creation_clause_list /= Void then
  1153.            creation_clause_list.pretty_print;
  1154.         end;
  1155.         if feature_clause_list /= Void then
  1156.            feature_clause_list.pretty_print;
  1157.         end;
  1158.         if class_invariant /= Void then
  1159.            class_invariant.pretty_print;
  1160.         end;
  1161.         fmt.set_indent_level(0);
  1162.         if fmt.zen_mode then
  1163.            fmt.skip(0);
  1164.         else
  1165.            fmt.skip(1);
  1166.         end;
  1167.         fmt.keyword(fz_end);
  1168.         if end_comment /= Void and then not end_comment.dummy then
  1169.            end_comment.pretty_print;
  1170.         elseif not fmt.zen_mode then
  1171.            fmt.put_string("-- class ");
  1172.            fmt.put_string(name.to_string);
  1173.         end;
  1174.         if fmt.column /= 1 then
  1175.            fmt.put_character('%N');
  1176.         end;
  1177.      end;
  1178.  
  1179. feature {NONE}
  1180.  
  1181.    error_vtec1 is
  1182.       do
  1183.      error(name.start_position,
  1184.            "A class cannot be expanded and deferred (VTEC.1).");
  1185.       end;
  1186.  
  1187. feature {FEATURE_NAME,E_FEATURE}
  1188.  
  1189.    fatal_undefine(fn: FEATURE_NAME) is
  1190.       do
  1191.      eh.append("Problem with undefine of %"");
  1192.      eh.append(fn.to_string);
  1193.      eh.append("%" in %"");
  1194.      eh.append(name.to_string);
  1195.      fatal_error("%".");
  1196.       end;
  1197.  
  1198. feature {TYPE,PARENT}
  1199.  
  1200.    is_a_vncg(t1, t2: TYPE): BOOLEAN is
  1201.      -- Direct conformance VNCG
  1202.       require
  1203.      t1.is_run_type;
  1204.      t2.is_run_type;
  1205.      t1.base_class = Current;
  1206.      t2.generic_list /= Void;
  1207.      eh.is_empty
  1208.       do
  1209.      if parent_list /= Void then
  1210.         Result := parent_list.is_a_vncg(t1.run_type,t2.run_type);
  1211.      end;
  1212.       ensure
  1213.      eh.is_empty
  1214.       end;
  1215.  
  1216. feature {NONE}
  1217.  
  1218.    vdrd6(rc: RUN_CLASS; super, redef: E_FEATURE) is
  1219.       require
  1220.      super /= Void;
  1221.      redef /= Void;
  1222.      super /= redef
  1223.       local
  1224.      writable_attribute: WRITABLE_ATTRIBUTE;
  1225.      ct, rt1, rt2: TYPE;
  1226.       do
  1227.      writable_attribute ?= super;
  1228.      if writable_attribute /= Void then
  1229.         writable_attribute ?= redef;
  1230.         if writable_attribute = Void then
  1231.            fatal_error_vdrd6(super,redef,
  1232.                  "An attribute must be redefined as an attribute %
  1233.                  %only (VDRD.6).");
  1234.         else
  1235.            ct := rc.current_type;
  1236.            rt1 := super.result_type.to_runnable(ct);
  1237.            rt2 := redef.result_type.to_runnable(ct);
  1238.            if rt1.is_reference then
  1239.           if rt2.is_reference then
  1240.           else
  1241.              fatal_error_vdrd6(super,redef,vdrd6_types);
  1242.           end;
  1243.            elseif rt2.is_reference then
  1244.           fatal_error_vdrd6(super,redef,vdrd6_types);
  1245.            end;
  1246.         end;
  1247.      end;
  1248.       end;
  1249.  
  1250.    vdrd6_types: STRING is "Result types must be both expanded or %
  1251.    %both non-expanded (VDRD.6)."
  1252.  
  1253.    fatal_error_vdrd6(super, redef: E_FEATURE; msg: STRING) is
  1254.       do
  1255.      eh.add_position(super.start_position);
  1256.      eh.add_position(redef.start_position);
  1257.      eh.append("Bad redefinition. ");
  1258.      eh.append(msg);
  1259.      eh.print_as_fatal_error;
  1260.       end;
  1261.  
  1262. invariant
  1263.  
  1264.    name /= Void;
  1265.  
  1266. end -- BASE_CLASS
  1267.